<?php

namespace app\user\logic;

vendor('alidayu.SmsDemo');

use app\Api;
use app\user\logic\SaveSMS as IndexLogicSaveSMS;

/**
 * 发送短信验证码相关类
 * Class NoteCode
 * @package app\index\logic
 */
class SMS extends Api
{
    private static $obj = null;

    public function _initialize()
    {
        parent::_initialize();
    }

    /**
     * 类入口
     * @return SMS|null
     */
    public static function getInstance()
    {
        if (is_null(self::$obj))
            self::$obj = new self();
        return self::$obj;
    }

    /**
     * 发送模板短信(阿里大鱼)
     * @param string $mobile 手机号码
     * @param int $code 验证码
     * @return bool
     */
    private function sendALiDaYuSMS($type, $mobile, $code)
    {
        $demo = new \SmsDemo(
            config('alidayu.access_key_id'),
            config('alidayu.access_key_secret')
        );

        $response = $demo->sendSms(
            config('alidayu.sign_name'), // 短信签名
            config('alidayu.template_code_' . $type), // 短信模板编号
            $mobile, // 短信接收者
            Array(  // 短信模板中字段的值
                "code" => $code,
            ),
            config('alidayu.out_id') // 发送短信流水号
        );
        $resp = _objectToArray($response);

        if (!isset($resp['Message']) || !isset($resp['Code'])) return false;

        // 当Code等于 isv.BUSINESS_LIMIT_CONTROL 时，触发分钟级流控Permits:1
        if ($resp['Message'] == 'OK' && $resp['Code'] == 'OK') {
            return true;
        }
    }

    /**
     * 发送短信
     * @param $mobile
     * @param $code
     * @return bool
     */
    private function toSendSMS($type, $mobile, $code)
    {
        return $this->sendALiDaYuSMS($type, $mobile, $code);
    }

    /**
     * 发送短信验证码
     * @param $type
     * @param $mobile
     * @param int $length
     * @return bool
     */
    public function sendSMS($type, $mobile, $length = 6)
    {
        if ($length == 4) {
            $code = rand(1000, 9999);
        } else {
            $code = rand(100000, 999999);
        }
        $pass_key = md5($type . '_' . $mobile . '_' . $this->_now . '_' . $code);
        $key = $this->getCacheKey($type, $mobile, $pass_key);
        if (!isset($key)) return false;

        // 保存短信验证码信息
        $bool_result = IndexLogicSaveSMS::getInstance()->saveSMS($key, ['mobile' => $mobile, 'code' => $code, 'pass_key' => $pass_key]);
        if ($bool_result == false) return '>5';
        // 短信验证码信息保存成功后继续
        if (!isset($bool_result)) return false;

        $bool_res = $this->toSendSMS($type, $mobile, $code);
        if ($bool_res === true) {
            return $pass_key;
        } else {
            return false;
        }
    }

    /**
     * 验证短信验证码是否正确
     * @param $type
     * @param $mobile
     * @param $pass_key
     * @param $code
     * @param $is_rm
     */
    public function verifySMS($type, $mobile, $pass_key, $code, $is_rm = true)
    {
        $str_key = $this->getCacheKey($type, $mobile, $pass_key);

        $arr_data = IndexLogicSaveSMS::getInstance()->getSMS($str_key);
        if (!isset($arr_data['mobile']) || !isset($arr_data['code']) || !isset($arr_data['pass_key'])) return false;

        if ($mobile != $arr_data['mobile']) return false;

        if ($code != $arr_data['code']) return false;

        if ($pass_key != $arr_data['pass_key']) return false;

        if ($is_rm === true) {
            // 删除记录
            IndexLogicSaveSMS::getInstance()->delSMS($str_key);
        }

        return true;
    }

    /**
     * 获取缓存key
     * @param $type
     * @param $mobile
     * @param $pass_key
     * @return bool|string
     */
    private function getCacheKey($type, $mobile, $pass_key)
    {
        $key = '';
        switch ($type) {
            case 'login': // 登录
                $key .= 'fp_login_' . $mobile . '_' . $pass_key;
                break;
            case 'forget': // 忘记密码
                $key .= 'fp_forget_' . $mobile . '_' . $pass_key;
                break;
            case 'auth': // 身份验证
                $key .= 'fp_auth_' . $mobile . '_' . $pass_key;
                break;
            case 'bank_card': // 身份验证
                $key .= 'fp_bank_card_' . $mobile . '_' . $pass_key;
                break;
            case 'pay_password': // 身份验证
                $key .= 'fp_pay_password_' . $mobile . '_' . $pass_key;
                break;

            default:
                return false;
        }
        return $key;
    }
}
